"""
性能管理模块 - 数据模型
提供系统性能监控、优化和缓存管理
"""
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.core.cache import cache
from django.conf import settings
import uuid
import json
import time

from apps.core.models import TimeStampedModel

User = get_user_model()


class PerformanceMonitor(TimeStampedModel):
    """
    性能监控
    记录系统各项性能指标
    """
    class MetricType(models.TextChoices):
        RESPONSE_TIME = 'response_time', '响应时间'
        THROUGHPUT = 'throughput', '吞吐量'
        ERROR_RATE = 'error_rate', '错误率'
        CPU_USAGE = 'cpu_usage', 'CPU使用率'
        MEMORY_USAGE = 'memory_usage', '内存使用率'
        DISK_USAGE = 'disk_usage', '磁盘使用率'
        DATABASE_PERFORMANCE = 'db_performance', '数据库性能'
        CACHE_HIT_RATE = 'cache_hit_rate', '缓存命中率'

    class Component(models.TextChoices):
        WEB_SERVER = 'web_server', 'Web服务器'
        APPLICATION = 'application', '应用服务器'
        DATABASE = 'database', '数据库'
        CACHE = 'cache', '缓存'
        EXTERNAL_API = 'external_api', '外部API'
        BACKGROUND_TASK = 'background_task', '后台任务'

    metric_type = models.CharField('指标类型', max_length=30, choices=MetricType.choices)
    component = models.CharField('组件', max_length=30, choices=Component.choices)
    metric_value = models.DecimalField('指标值', max_digits=10, decimal_places=4)

    # 标识信息
    instance_id = models.CharField('实例ID', max_length=100, blank=True)
    server_name = models.CharField('服务器名称', max_length=100, blank=True)

    # 时间和频率
    recorded_at = models.DateTimeField('记录时间', auto_now_add=True)
    time_period = models.CharField('时间周期', max_length=20, default='minute')

    # 阈值设置
    warning_threshold = models.DecimalField('警告阈值', max_digits=10, decimal_places=4, null=True, blank=True)
    critical_threshold = models.DecimalField('严重阈值', max_digits=10, decimal_places=4, null=True, blank=True)

    # 状态
    status = models.CharField(
        '状态',
        max_length=20,
        choices=[
            ('normal', '正常'),
            ('warning', '警告'),
            ('critical', '严重'),
            ('unknown', '未知'),
        ],
        default='normal'
    )

    # 额外数据
    metadata = models.JSONField('元数据', default=dict, blank=True)
    tags = models.JSONField('标签', default=list, blank=True)

    class Meta:
        db_table = 'performance_monitors'
        verbose_name = '性能监控'
        verbose_name_plural = '性能监控'
        ordering = ['-recorded_at']
        indexes = [
            models.Index(fields=['metric_type', 'recorded_at']),
            models.Index(fields=['component', 'status']),
            models.Index(fields=['recorded_at']),
            models.Index(fields=['status']),
        ]

    def __str__(self):
        return f"{self.component} - {self.get_metric_type_display()}: {self.metric_value}"

    def check_thresholds(self):
        """检查是否超过阈值"""
        if self.critical_threshold and self.metric_value >= self.critical_threshold:
            self.status = 'critical'
        elif self.warning_threshold and self.metric_value >= self.warning_threshold:
            self.status = 'warning'
        else:
            self.status = 'normal'
        self.save(update_fields=['status'])


class CacheManagement(TimeStampedModel):
    """
    缓存管理
    管理系统缓存策略和缓存状态
    """
    class CacheType(models.TextChoices):
        MEMORY = 'memory', '内存缓存'
        REDIS = 'redis', 'Redis缓存'
        DATABASE = 'database', '数据库查询缓存'
        SESSION = 'session', '会话缓存'
        TEMPLATE = 'template', '模板缓存'
        STATIC = 'static', '静态文件缓存'

    cache_key = models.CharField('缓存键', max_length=255)
    cache_type = models.CharField('缓存类型', max_length=20, choices=CacheType.choices)

    # 缓存内容
    content_type = models.CharField('内容类型', max_length=100)
    content_size = models.IntegerField('内容大小(字节)', null=True, blank=True)

    # 时间信息
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    expires_at = models.DateTimeField('过期时间', null=True, blank=True)
    last_accessed = models.DateTimeField('最后访问时间', null=True, blank=True)

    # 访问统计
    access_count = models.IntegerField('访问次数', default=0)
    hit_rate = models.DecimalField('命中率', max_digits=5, decimal_places=2, default=0)

    # 缓存策略
    ttl = models.IntegerField('生存时间(秒)', null=True, blank=True)
    eviction_policy = models.CharField('淘汰策略', max_length=50, default='lru')

    # 状态
    is_active = models.BooleanField('是否活跃', default=True)
    is_warm = models.BooleanField('是否预热', default=False)

    # 关联对象
    content_type_field = models.ForeignKey(
        'contenttypes.ContentType',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='cache_entries'
    )
    object_id = models.UUIDField('对象ID', null=True, blank=True)
    related_object = models.GenericForeignKey('content_type_field', 'object_id')

    class Meta:
        db_table = 'cache_management'
        verbose_name = '缓存管理'
        verbose_name_plural = '缓存管理'
        ordering = ['-last_accessed']
        indexes = [
            models.Index(fields=['cache_key']),
            models.Index(fields=['cache_type', 'is_active']),
            models.Index(fields=['expires_at']),
            models.Index(fields=['last_accessed']),
            models.Index(fields=['hit_rate']),
        ]

    def __str__(self):
        return f"{self.cache_key} ({self.get_cache_type_display()})"

    def is_expired(self):
        """检查缓存是否过期"""
        if not self.expires_at:
            return False
        return timezone.now() > self.expires_at

    def record_access(self):
        """记录访问"""
        self.access_count += 1
        self.last_accessed = timezone.now()
        self.hit_rate = self._calculate_hit_rate()
        self.save(update_fields=['access_count', 'last_accessed', 'hit_rate'])

    def _calculate_hit_rate(self):
        """计算命中率"""
        if self.access_count <= 1:
            return 0
        return ((self.access_count - 1) / self.access_count) * 100


class DatabaseOptimization(TimeStampedModel):
    """
    数据库优化
    记录数据库优化措施和效果
    """
    class OptimizationType(models.TextChoices):
        INDEX = 'index', '索引优化'
        QUERY = 'query', '查询优化'
        PARTITION = 'partition', '分区优化'
        CACHING = 'caching', '查询缓存'
        CONNECTION = 'connection', '连接优化'
        STRUCTURE = 'structure', '结构优化'

    optimization_type = models.CharField('优化类型', max_length=30, choices=OptimizationType.choices)
    table_name = models.CharField('表名', max_length=100)

    # 优化描述
    description = models.TextField('优化描述')
    implementation_sql = models.TextField('执行SQL', blank=True)

    # 优化前后对比
    before_performance = models.JSONField('优化前性能', default=dict)
    after_performance = models.JSONField('优化后性能', default=dict)

    # 效果评估
    improvement_percentage = models.DecimalField('改善百分比', max_digits=5, decimal_places=2, null=True, blank=True)
    performance_gain = models.TextField('性能提升', blank=True)

    # 状态
    status = models.CharField(
        '状态',
        max_length=20,
        choices=[
            ('planned', '计划中'),
            ('implemented', '已实施'),
            ('tested', '已测试'),
            ('deployed', '已部署'),
            ('reverted', '已回滚'),
        ],
        default='planned'
    )

    # 实施信息
    implemented_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='database_optimizations',
        verbose_name='实施者',
        null=True,
        blank=True
    )
    implemented_at = models.DateTimeField('实施时间', null=True, blank=True)

    # 风险评估
    risk_level = models.CharField(
        '风险等级',
        max_length=20,
        choices=[
            ('low', '低风险'),
            ('medium', '中风险'),
            ('high', '高风险'),
        ],
        default='medium'
    )
    rollback_plan = models.TextField('回滚计划', blank=True)

    class Meta:
        db_table = 'database_optimizations'
        verbose_name = '数据库优化'
        verbose_name_plural = '数据库优化'
        ordering = ['-implemented_at']
        indexes = [
            models.Index(fields=['optimization_type', 'status']),
            models.Index(fields=['table_name']),
            models.Index(fields=['implemented_at']),
            models.Index(fields=['risk_level']),
        ]

    def __str__(self):
        return f"{self.table_name} - {self.get_optimization_type_display()}"

    def calculate_improvement(self):
        """计算性能改善百分比"""
        if not self.before_performance or not self.after_performance:
            return

        before_time = self.before_performance.get('query_time', 0)
        after_time = self.after_performance.get('query_time', 0)

        if before_time > 0:
            improvement = ((before_time - after_time) / before_time) * 100
            self.improvement_percentage = improvement
            self.save(update_fields=['improvement_percentage'])


class LoadBalancing(TimeStampedModel):
    """
    负载均衡
    管理服务器负载和分配策略
    """
    class Strategy(models.TextChoices):
        ROUND_ROBIN = 'round_robin', '轮询'
        LEAST_CONNECTIONS = 'least_connections', '最少连接'
        WEIGHTED = 'weighted', '加权'
        IP_HASH = 'ip_hash', 'IP哈希'
        RANDOM = 'random', '随机'

    server_name = models.CharField('服务器名称', max_length=100)
    server_ip = models.GenericIPAddressField('服务器IP')
    server_port = models.IntegerField('服务器端口', default=80)

    # 负载均衡策略
    strategy = models.CharField('策略', max_length=30, choices=Strategy.choices)
    weight = models.IntegerField('权重', default=1)

    # 服务器状态
    is_active = models.BooleanField('是否活跃', default=True)
    is_healthy = models.BooleanField('是否健康', default=True)
    current_connections = models.IntegerField('当前连接数', default=0)
    max_connections = models.IntegerField('最大连接数', default=1000)

    # 性能指标
    cpu_usage = models.DecimalField('CPU使用率', max_digits=5, decimal_places=2, null=True, blank=True)
    memory_usage = models.DecimalField('内存使用率', max_digits[5], decimal_places=2, null=True, blank=True)
    response_time = models.DecimalField('响应时间', max_digits=6, decimal_places=3, null=True, blank=True)

    # 健康检查
    health_check_url = models.URLField('健康检查URL', blank=True)
    health_check_interval = models.IntegerField('检查间隔(秒)', default=30)
    last_health_check = models.DateTimeField('最后健康检查', null=True, blank=True)

    # 故障转移
    failover_server = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        related_name='failover_servers',
        verbose_name='故障转移服务器',
        null=True,
        blank=True
    )

    class Meta:
        db_table = 'load_balancing'
        verbose_name = '负载均衡'
        verbose_name_plural = '负载均衡'
        indexes = [
            models.Index(fields=['is_active', 'is_healthy']),
            models.Index(fields=['current_connections']),
            models.Index(fields=['last_health_check']),
            models.Index(fields=['strategy']),
        ]

    def __str__(self):
        return f"{self.server_name} ({self.server_ip}:{self.server_port})"

    def get_load_percentage(self):
        """获取负载百分比"""
        if self.max_connections == 0:
            return 0
        return (self.current_connections / self.max_connections) * 100

    def is_overloaded(self):
        """检查是否过载"""
        return self.get_load_percentage() > 80

    def perform_health_check(self):
        """执行健康检查"""
        # 这里实现实际的健康检查逻辑
        import requests
        try:
            if self.health_check_url:
                response = requests.get(
                    self.health_check_url,
                    timeout=5
                )
                self.is_healthy = response.status_code == 200
            else:
                self.is_healthy = True  # 简单的连通性检查

            self.last_health_check = timezone.now()
            self.save(update_fields=['is_healthy', 'last_health_check'])

        except Exception:
            self.is_healthy = False
            self.last_health_check = timezone.now()
            self.save(update_fields=['is_healthy', 'last_health_check'])


class ApiRateLimiting(TimeStampedModel):
    """
    API限流
    管理API接口的访问频率限制
    """
    class LimitType(models.TextChoices):
        IP_BASED = 'ip_based', '基于IP'
        USER_BASED = 'user_based', '基于用户'
        ENDPOINT_BASED = 'endpoint_based', '基于接口'
        GLOBAL = 'global', '全局'

    api_endpoint = models.CharField('API接口', max_length=200)
    limit_type = models.CharField('限制类型', max_length=30, choices=LimitType.choices)

    # 限制配置
    requests_per_minute = models.IntegerField('每分钟请求限制', default=60)
    requests_per_hour = models.IntegerField('每小时请求限制', default=1000)
    requests_per_day = models.IntegerField('每日请求限制', default=10000)

    # 突发处理
    burst_capacity = models.IntegerField('突发容量', default=10)
    burst_refill_rate = models.IntegerField('突发恢复速率', default=1)

    # 状态
    is_active = models.BooleanField('是否启用', default=True)

    # 统计信息
    total_requests = models.IntegerField('总请求数', default=0)
    blocked_requests = models.IntegerField('被阻止请求数', default=0)
    current_usage = models.JSONField('当前使用情况', default=dict, blank=True)

    # 特殊规则
    whitelist_ips = models.JSONField('IP白名单', default=list, blank=True)
    whitelist_users = models.ManyToManyField(
        User,
        related_name='rate_limit_exceptions',
        verbose_name='白名单用户',
        blank=True
    )

    class Meta:
        db_table = 'api_rate_limiting'
        verbose_name = 'API限流'
        verbose_name_plural = 'API限流'
        unique_together = [['api_endpoint', 'limit_type']]
        indexes = [
            models.Index(fields=['api_endpoint', 'is_active']),
            models.Index(fields=['limit_type']),
            models.Index(fields=['is_active']),
        ]

    def __str__(self):
        return f"{self.api_endpoint} - {self.get_limit_type_display()}"

    def is_rate_limited(self, identifier, current_time=None):
        """检查是否达到限制"""
        if not self.is_active:
            return False

        if not current_time:
            current_time = timezone.now()

        # 获取当前使用情况
        usage_key = f"rate_limit:{self.api_endpoint}:{self.limit_type}:{identifier}"
        current_usage = cache.get(usage_key, {})

        # 检查各种限制
        if self._check_minute_limit(current_usage, current_time):
            return True

        if self._check_hour_limit(current_usage, current_time):
            return True

        if self._check_day_limit(current_usage, current_time):
            return True

        return False

    def _check_minute_limit(self, usage, current_time):
        """检查分钟限制"""
        minute_key = current_time.strftime('%Y%m%d%H%M')
        minute_count = usage.get(minute_key, 0)
        return minute_count >= self.requests_per_minute

    def _check_hour_limit(self, usage, current_time):
        """检查小时限制"""
        hour_key = current_time.strftime('%Y%m%d%H')
        hour_count = usage.get(hour_key, 0)
        return hour_count >= self.requests_per_hour

    def _check_day_limit(self, usage, current_time):
        """检查日限制"""
        day_key = current_time.strftime('%Y%m%d')
        day_count = usage.get(day_key, 0)
        return day_count >= self.requests_per_day

    def record_request(self, identifier, blocked=False):
        """记录请求"""
        current_time = timezone.now()
        usage_key = f"rate_limit:{self.api_endpoint}:{self.limit_type}:{identifier}"

        current_usage = cache.get(usage_key, {})

        # 更新统计
        self.total_requests += 1
        if blocked:
            self.blocked_requests += 1

        # 更新使用计数
        minute_key = current_time.strftime('%Y%m%d%H%M')
        hour_key = current_time.strftime('%Y%m%d%H')
        day_key = current_time.strftime('%Y%m%d')

        current_usage[minute_key] = current_usage.get(minute_key, 0) + 1
        current_usage[hour_key] = current_usage.get(hour_key, 0) + 1
        current_usage[day_key] = current_usage.get(day_key, 0) + 1

        # 缓存更新
        cache.set(usage_key, current_usage, 86400)  # 缓存24小时
        self.current_usage = current_usage

        self.save(update_fields=['total_requests', 'blocked_requests', 'current_usage'])


class SystemResource(TimeStampedModel):
    """
    系统资源监控
    监控服务器资源使用情况
    """
    server_name = models.CharField('服务器名称', max_length=100, unique=True)

    # CPU信息
    cpu_cores = models.IntegerField('CPU核心数', default=0)
    cpu_usage = models.DecimalField('CPU使用率', max_digits=5, decimal_places=2, null=True, blank=True)
    cpu_load_1min = models.DecimalField('1分钟负载', max_digits=5, decimal_places=2, null=True, blank=True)
    cpu_load_5min = models.DecimalField('5分钟负载', max_digits=5, decimal_places=2, null=True, blank=True)
    cpu_load_15min = models.DecimalField('15分钟负载', max_digits=5, decimal_places=2, null=True, blank=True)

    # 内存信息
    total_memory = models.BigIntegerField('总内存(字节)', default=0)
    used_memory = models.BigIntegerField('已用内存(字节)', default=0)
    available_memory = models.BigIntegerField('可用内存(字节)', default=0)
    memory_usage = models.DecimalField('内存使用率', max_digits=5, decimal_places=2, null=True, blank=True)

    # 磁盘信息
    total_disk = models.BigIntegerField('总磁盘空间(字节)', default=0)
    used_disk = models.BigIntegerField('已用磁盘空间(字节)', default=0)
    available_disk = models.BigIntegerField('可用磁盘空间(字节)', default=0)
    disk_usage = models.DecimalField('磁盘使用率', max_digits=5, decimal_places=2, null=True, blank=True)

    # 网络信息
    network_in = models.BigIntegerField('网络入流量(字节)', default=0)
    network_out = models.BigIntegerField('网络出流量(字节)', default=0)

    # 进程信息
    process_count = models.IntegerField('进程数', null=True, blank=True)
    thread_count = models.IntegerField('线程数', null=True, blank=True)

    # 系统信息
    uptime = models.IntegerField('运行时间(秒)', null=True, blank=True)
    os_type = models.CharField('操作系统类型', max_length=50, blank=True)
    os_version = models.CharField('操作系统版本', max_length=100, blank=True)

    # 状态
    is_healthy = models.BooleanField('是否健康', default=True)
    last_updated = models.DateTimeField('最后更新时间', auto_now=True)

    # 告警阈值
    cpu_warning_threshold = models.DecimalField('CPU警告阈值', max_digits=5, decimal_places=2, default=80)
    memory_warning_threshold = models.DecimalField('内存警告阈值', max_digits=5, decimal_places=2, default=80)
    disk_warning_threshold = models.DecimalField('磁盘警告阈值', max_digits=5, decimal_places=2, default=80)

    class Meta:
        db_table = 'system_resources'
        verbose_name = '系统资源'
        verbose_name_plural = '系统资源'
        indexes = [
            models.Index(fields=['server_name']),
            models.Index(fields=['is_healthy']),
            models.Index(fields=['last_updated']),
        ]

    def __str__(self):
        return f"{self.server_name} - {'健康' if self.is_healthy else '异常'}"

    def check_health(self):
        """检查系统健康状态"""
        issues = []

        if self.cpu_usage and self.cpu_usage > self.cpu_warning_threshold:
            issues.append(f"CPU使用率过高: {self.cpu_usage}%")

        if self.memory_usage and self.memory_usage > self.memory_warning_threshold:
            issues.append(f"内存使用率过高: {self.memory_usage}%")

        if self.disk_usage and self.disk_usage > self.disk_warning_threshold:
            issues.append(f"磁盘使用率过高: {self.disk_usage}%")

        self.is_healthy = len(issues) == 0
        self.save(update_fields=['is_healthy'])
        return issues

    def get_memory_percentage(self):
        """获取内存使用百分比"""
        if self.total_memory == 0:
            return 0
        return (self.used_memory / self.total_memory) * 100

    def get_disk_percentage(self):
        """获取磁盘使用百分比"""
        if self.total_disk == 0:
            return 0
        return (self.used_disk / self.total_disk) * 100